package com.css.fxfzypg.modules.rating.library.service;

import cn.hutool.core.util.IdUtil;
import com.css.fxfzypg.constants.YNEnum;
import com.css.fxfzypg.modules.rating.library.dao.*;
import com.css.fxfzypg.modules.rating.library.model.dto.*;
import com.css.fxfzypg.modules.rating.library.model.entity.*;
import com.css.fxfzypg.modules.rating.library.model.vo.GetIndexListByKesdIdVo;
import com.css.fxfzypg.modules.rating.library.model.vo.GetLatestUnsaveIndexVo;
import com.css.fxfzypg.modules.rating.library.service.cache.KpIndex3DataCacheService;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.ObjectUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.HashOperations;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Date;
import java.util.Iterator;
import java.util.List;

/**
 * 考评库新建管理服务
 */
@Slf4j
@Service
public class KpExamScoringDbNewService {

    @Autowired
    KpExamScoringDbService kpExamScoringDbService;
    @Autowired
    KpIndex3DataCacheService kpIndex3DataCacheService;
    @Autowired
    private RedisTemplate redisTemplate;
    @Autowired
    private KpExamScoringDbIndex1Repository kpExamScoringDbIndex1Repository;
    @Autowired
    private KpExamScoringDbIndex2Repository kpExamScoringDbIndex2Repository;
    @Autowired
    private KpExamScoringDbIndex3Repository kpExamScoringDbIndex3Repository;
    @Autowired
    private KpExamScoringDbRepository kpExamScoringDbRepository;
    @Autowired
    KpExamIndex3PeekDataDao kpExamIndex3PeekDataDao;

    /**
     * 查询最新未提交的数据
     *
     * @param currUid
     * @return
     */
    public GetLatestUnsaveIndexVo getLatestUnsaveIndex(String currUid) {
        GetLatestUnsaveIndexVo getLatestUnsaveIndexVo = new GetLatestUnsaveIndexVo();
        List<GetIndexListByKesdIdVo> resList = new ArrayList<>();
        KpExamScoringDbInserIndexCacheDto latestCreateKpkFromCache = kpExamScoringDbService.findLatestCreateKpkFromCache(currUid);
        if (latestCreateKpkFromCache.getIndexData() == null) {
            return null;
        }
        for (KpExamScoringDbIndex1InsertCacheDto index1 : latestCreateKpkFromCache.getIndexData()) {
            for (KpExamScoringDbIndex2InsertCacheDto index2 : index1.getChildren()) {
                for (KpExamScoringDbIndex3 index3 : index2.getChildren()) {
                    GetIndexListByKesdIdVo indexVo = new GetIndexListByKesdIdVo();
                    indexVo.setIndex1Id(index1.getId());
                    indexVo.setIndex1Name(index1.getName());
                    indexVo.setIndex1Score(index1.getScore());
                    indexVo.setIndex2Id(index2.getId());
                    indexVo.setIndex2Name(index2.getName());
                    indexVo.setIndex2Score(index2.getScore());
                    indexVo.setIndex3Id(index3.getId());
                    indexVo.setKpIndex3Data(kpIndex3DataCacheService.getById(index3.getKpi3dId()));
                    indexVo.setIndex3Score(index3.getScore());
                    indexVo.setIndex3Standard(index3.getIndexStandard());
                    indexVo.setPtgxTypeCodes(index3.getPtgxTypeCodes());
                    resList.add(indexVo);
                }
            }
        }
        getLatestUnsaveIndexVo.setList(resList);
        getLatestUnsaveIndexVo.setName(latestCreateKpkFromCache.getKesdName());
        return getLatestUnsaveIndexVo;
    }

    /**
     * 删除考评库
     *
     * @param currUid
     */
    public void deleteKpk(String currUid) {
        redisTemplate.opsForHash().delete(KpExamScoringDbService.CURR_USER_LATEST_CREATE_KPK, currUid);
    }

    /**
     * 根据id删除指标
     *
     * @param index3Id
     * @param currUid
     */
    public void deleteIndexById(String index3Id, String currUid) {
        KpExamScoringDbInserIndexCacheDto latestCreateKpkFromCache = kpExamScoringDbService.findLatestCreateKpkFromCache(currUid);
        Iterator<KpExamScoringDbIndex1InsertCacheDto> index1It = latestCreateKpkFromCache.getIndexData().iterator();
        while (index1It.hasNext()) {
            KpExamScoringDbIndex1InsertCacheDto index1 = index1It.next();
            Iterator<KpExamScoringDbIndex2InsertCacheDto> index2It = index1.getChildren().iterator();
            while (index2It.hasNext()) {
                KpExamScoringDbIndex2InsertCacheDto index2 = index2It.next();
                index2.getChildren().removeIf(index3 -> index3.getId().equals(index3Id));
                if (index2.getChildren().size() == 0) {
                    index2It.remove();
                }
            }
            if (index1.getChildren().size() == 0) {
                index1It.remove();
            }
        }
        HashOperations<String, String, KpExamScoringDbInserIndexCacheDto> hashOps = redisTemplate.opsForHash();
        hashOps.put(KpExamScoringDbService.CURR_USER_LATEST_CREATE_KPK, currUid, latestCreateKpkFromCache);
    }

    @Transactional(rollbackFor = Exception.class)
    public void commit(String name, String currUid) throws Exception {
        Date currTime = new Date();
        KpExamScoringDbInserIndexCacheDto latestCreateKpkFromCache = kpExamScoringDbService.findLatestCreateKpkFromCache(currUid);
        List<KpExamScoringDbIndex1InsertCacheDto> indexList = latestCreateKpkFromCache.getIndexData();
        if (indexList == null) {
            throw new Exception("请至少一条添加指标数据");
        }
        if (StringUtils.isNotBlank(name)) {
            latestCreateKpkFromCache.setKesdName(name);
        }
        KpExamScoringDb kpExamScoringDb = new KpExamScoringDb();
        kpExamScoringDb.setId(latestCreateKpkFromCache.getKesdId());
        kpExamScoringDb.setName(latestCreateKpkFromCache.getKesdName());
        kpExamScoringDb.setCreateTime(currTime);
        kpExamScoringDb.setCreateUser(currUid);
        kpExamScoringDb.setDelFlag(YNEnum.N.toString());
        kpExamScoringDb.setUpdateTime(currTime);
        kpExamScoringDb.setUpdateUser(currUid);
        List<KpExamScoringDbIndex1> index1List = new ArrayList<>();
        List<KpExamScoringDbIndex2> index2List = new ArrayList<>();
        List<KpExamScoringDbIndex3> index3List = new ArrayList<>();
        for (KpExamScoringDbIndex1InsertCacheDto index1 : indexList) {
            KpExamScoringDbIndex1 kpExamScoringDbIndex1 = new KpExamScoringDbIndex1();
//            kpExamScoringDbIndex1.setId(index1.getId());
            kpExamScoringDbIndex1.setId(IdUtil.simpleUUID());
//            kpExamScoringDbIndex1.setScore(index1.getScore());
            kpExamScoringDbIndex1.setName(index1.getName());
            kpExamScoringDbIndex1.setKesdId(index1.getKesdId());
            kpExamScoringDbIndex1.setCreateTime(index1.getCreateTime());
            index1List.add(kpExamScoringDbIndex1);
            for (KpExamScoringDbIndex2InsertCacheDto index2 : index1.getChildren()) {
                KpExamScoringDbIndex2 kpExamScoringDbIndex2 = new KpExamScoringDbIndex2();
//                kpExamScoringDbIndex2.setId(index2.getId());
                kpExamScoringDbIndex2.setId(IdUtil.simpleUUID());
                kpExamScoringDbIndex2.setName(index2.getName());
//                kpExamScoringDbIndex2.setScore(index2.getScore());
                kpExamScoringDbIndex2.setKpesdi1Id(kpExamScoringDbIndex1.getId());
                kpExamScoringDbIndex2.setCreateTime(index2.getCreateTime());
                index2List.add(kpExamScoringDbIndex2);
                for (KpExamScoringDbIndex3 index3 : index2.getChildren()) {
                    KpExamScoringDbIndex3 kpExamScoringDbIndex3 = new KpExamScoringDbIndex3();
                    kpExamScoringDbIndex3.setId(index3.getId());
                    kpExamScoringDbIndex3.setKpesdi2Id(kpExamScoringDbIndex2.getId());
                    kpExamScoringDbIndex3.setKpi3dId(index3.getKpi3dId());
                    kpExamScoringDbIndex3.setScore(index3.getScore());
                    kpExamScoringDbIndex3.setIndexStandard(index3.getIndexStandard());
                    kpExamScoringDbIndex3.setCreateTime(index3.getCreateTime());
                    index3List.add(kpExamScoringDbIndex3);
                    KpIndex3Data kpIndex3Data = kpIndex3DataCacheService.getById(index3.getKpi3dId());
                    if (kpIndex3Data != null && kpIndex3Data.getCode() != null && kpIndex3Data.getCode().equals("26") && StringUtils.isNotBlank(index3.getPtgxTypeCodes())) {
                        String[] typeCode = index3.getPtgxTypeCodes().split(",");
                        for (String code : typeCode) {
                            KpExamIndex3PeekData peekData = new KpExamIndex3PeekData();
                            peekData.setId(IdUtil.simpleUUID());
                            peekData.setKesdi3Id(index3.getId());
                            peekData.setDataTypeCode(code);
                            peekData.setCreateTime(new Date());
                            peekData.setCreateUser(currUid);
                            kpExamIndex3PeekDataDao.insert(peekData);
                        }
                    }
                }
            }
        }
        kpExamScoringDbRepository.insert(kpExamScoringDb);
        kpExamScoringDbIndex1Repository.batchSave(index1List);
        kpExamScoringDbIndex2Repository.batchSave(index2List);
        kpExamScoringDbIndex3Repository.batchSave(index3List);
        redisTemplate.opsForHash().delete(KpExamScoringDbService.CURR_USER_LATEST_CREATE_KPK, currUid);
    }

    /**
     * 保存指标
     *
     * @param indexDto
     * @param currUid
     * @return
     */
    public synchronized KpExamScoringDbNewInsertIndexDto applyIndex(KpExamScoringDbNewInsertIndexDto indexDto, String currUid) {
        // 从缓存查询当前用户最新未提交的创建的考评库
        KpExamScoringDbInserIndexCacheDto kpExamScoringDbInserIndexCacheDto = kpExamScoringDbService.findLatestCreateKpkFromCache(currUid);
        kpExamScoringDbInserIndexCacheDto.setKesdName(indexDto.getKesdName());
        List<KpExamScoringDbIndex1InsertCacheDto> indexList = kpExamScoringDbInserIndexCacheDto.getIndexData();
        if (indexList == null) {
            indexList = new ArrayList<>();
            kpExamScoringDbInserIndexCacheDto.setIndexData(indexList);
        }
        for (KpExamScoringDbInsertIndexListDto dto : indexDto.getIndexList()) {
            // 处理1级
            boolean flag1 = false;
            for (KpExamScoringDbIndex1InsertCacheDto index1 : indexList) {
                if (index1.getId().equals(dto.getIndex1Id())) {
                    flag1 = true;
                    boolean flag2 = false;
                    BigDecimal index1Score = BigDecimal.ZERO;
                    // 处理2级
                    for (KpExamScoringDbIndex2InsertCacheDto index2 : index1.getChildren()) {
                        if (index2.getId().equals(dto.getIndex2Id())) {
                            flag2 = true;
                            boolean flag3 = false;
                            BigDecimal index2Score = BigDecimal.ZERO;
                            // 处理3级
                            for (KpExamScoringDbIndex3 index3 : index2.getChildren()) {
                                if (index3.getId().equals(dto.getIndex3Id())) {
                                    // 修改3级的信息
                                    index3.setIndexStandard(dto.getIndex3Standard());
                                    index3.setScore(dto.getIndex3Score());
                                    index3.setKpi3dId(dto.getIndex3Kpi3dId());
                                    index3.setKpesdi2Id(index2.getId());
                                    index3.setCreateTime(new Date());
                                    index3.setPtgxTypeCodes(dto.getPtgxTypeCodes());
                                    flag3 = true;
                                }
                                index2Score = index2Score.add(index3.getScore());
                            }
                            // 新增3级
                            if (!flag3) {
                                index2.getChildren().add(buildIndex3(dto, index2));
                                index2Score = index2Score.add(dto.getIndex3Score());
                            }
                            index2.setName(dto.getIndex2Name());
                            index2.setKpesdi1Id(index1.getId());
                            index2.setCreateTime(new Date());
                            index2.setScore(index2Score);
                            dto.setIndex2Score(index2Score);
                        }
                        index1Score = index1Score.add(index2.getScore());
                    }
                    if (!flag2) {
                        // 新增2级
                        index1.getChildren().add(buildIndex2(dto, index1));
                        index1Score = index1Score.add(dto.getIndex3Score());
                    }
                    index1.setName(dto.getIndex1Name());
                    index1.setKesdId(kpExamScoringDbInserIndexCacheDto.getKesdId());
                    index1.setCreateTime(new Date());
                    index1.setScore(index1Score);
                    dto.setIndex1Score(index1Score);
                }
            }
            if (!flag1) {
                // 新增1级
                indexList.add(buildIndex1(dto, kpExamScoringDbInserIndexCacheDto.getKesdId()));
            }
        }
        HashOperations<String, String, KpExamScoringDbInserIndexCacheDto> hashOps = redisTemplate.opsForHash();
        hashOps.put(KpExamScoringDbService.CURR_USER_LATEST_CREATE_KPK, currUid, kpExamScoringDbInserIndexCacheDto);
        return indexDto;
    }

    private static KpExamScoringDbIndex1InsertCacheDto findKpExamScoringDbIndex1InsertCacheDto(List<KpExamScoringDbIndex1InsertCacheDto> list, String sourceId) {
        if (list == null) {
            return null;
        }
        for (KpExamScoringDbIndex1InsertCacheDto index1 : list) {
            if (index1.getId().equals(sourceId)) {
                return index1;
            }
        }
        return null;
    }

    /**
     * 构建3级指标结构
     *
     * @return
     */
    private static KpExamScoringDbIndex3 buildIndex3(KpExamScoringDbInsertIndexListDto dto, KpExamScoringDbIndex2InsertCacheDto index2) {
        KpExamScoringDbIndex3 index3 = new KpExamScoringDbIndex3();
        index3.setId(IdUtil.simpleUUID());
        index3.setScore(dto.getIndex3Score());
        index3.setKpi3dId(dto.getIndex3Kpi3dId());
        index3.setIndexStandard(dto.getIndex3Standard());
        index3.setKpesdi2Id(index2.getId());
        index3.setPtgxTypeCodes(dto.getPtgxTypeCodes());
        return index3;
    }

    /**
     * 构建1级指标结构
     *
     * @return
     */
    private static KpExamScoringDbIndex1InsertCacheDto buildIndex1(KpExamScoringDbInsertIndexListDto dto, String kpkId) {
        KpExamScoringDbIndex1InsertCacheDto index1 = new KpExamScoringDbIndex1InsertCacheDto();
//        String index1Id = IdUtil.simpleUUID();
        index1.setId(dto.getIndex1Id());
        dto.setIndex1Id(dto.getIndex1Id());
        dto.setIndex1Score(dto.getIndex3Score());
        dto.setIndex2Score(dto.getIndex3Score());
        index1.setScore(dto.getIndex3Score());
        index1.setName(dto.getIndex1Name());
        index1.setKesdId(kpkId);

        List<KpExamScoringDbIndex2InsertCacheDto> index2List = new ArrayList<>();
        KpExamScoringDbIndex2InsertCacheDto index2 = new KpExamScoringDbIndex2InsertCacheDto();
        String index2Id = IdUtil.simpleUUID();
        index2.setId(dto.getIndex2Id());
        dto.setIndex2Id(dto.getIndex2Id());
        index2.setScore(dto.getIndex3Score());
        index2.setName(dto.getIndex2Name());
        index2.setKpesdi1Id(index1.getId());
        index2List.add(index2);
        index1.setChildren(index2List);

        List<KpExamScoringDbIndex3> index3List = new ArrayList<>();
        KpExamScoringDbIndex3 index3 = new KpExamScoringDbIndex3();
        String index3Id = IdUtil.simpleUUID();
        index3.setId(index3Id);
        dto.setIndex3Id(index3Id);
        index3.setScore(dto.getIndex3Score());
        index3.setKpi3dId(dto.getIndex3Kpi3dId());
        index3.setIndexStandard(dto.getIndex3Standard());
        index3.setKpesdi2Id(index2.getId());
        index3.setPtgxTypeCodes(dto.getPtgxTypeCodes());
        index3List.add(index3);
        index2.setChildren(index3List);
        return index1;
    }

    /**
     * 构建2级指标结构
     *
     * @return
     */
    private static KpExamScoringDbIndex2InsertCacheDto buildIndex2(KpExamScoringDbInsertIndexListDto dto, KpExamScoringDbIndex1InsertCacheDto index1) {
        KpExamScoringDbIndex2InsertCacheDto index2 = new KpExamScoringDbIndex2InsertCacheDto();
        index2.setId(dto.getIndex2Id());
        index2.setScore(dto.getIndex3Score());
        dto.setIndex2Score(dto.getIndex3Score());
        index2.setName(dto.getIndex2Name());
        index2.setKpesdi1Id(index1.getId());

        List<KpExamScoringDbIndex3> index3List = new ArrayList<>();
        KpExamScoringDbIndex3 index3 = new KpExamScoringDbIndex3();
        index3.setId(IdUtil.simpleUUID());
        index3.setScore(dto.getIndex3Score());
        index3.setKpi3dId(dto.getIndex3Kpi3dId());
        index3.setIndexStandard(dto.getIndex3Standard());
        index3.setKpesdi2Id(index2.getId());
        index3.setPtgxTypeCodes(dto.getPtgxTypeCodes());
        index3List.add(index3);
        index2.setChildren(index3List);
        return index2;
    }

    public void updatePtgxType(KpUpdatePtgxTypeDto dto, String uid) {
        // 从缓存查询当前用户最新未提交的创建的考评库
        KpExamScoringDbInserIndexCacheDto kpExamScoringDbInserIndexCacheDto = kpExamScoringDbService.findLatestCreateKpkFromCache(uid);
        for (KpExamScoringDbIndex1InsertCacheDto index1 : kpExamScoringDbInserIndexCacheDto.getIndexData()) {
            if (index1.getId().equals(dto.getIndex1Id())) {
                for (KpExamScoringDbIndex2InsertCacheDto index2 : index1.getChildren()) {
                    if (index2.getId().equals(dto.getIndex2Id())) {
                        for (KpExamScoringDbIndex3 index3 : index2.getChildren()) {
                            if (index3.getId().equals(dto.getIndex3Id())) {
                                index3.setPtgxTypeCodes(dto.getPtgxTypeCodes());
                            }
                        }
                    }
                }
            }
        }
        HashOperations<String, String, KpExamScoringDbInserIndexCacheDto> hashOps = redisTemplate.opsForHash();
        hashOps.put(KpExamScoringDbService.CURR_USER_LATEST_CREATE_KPK, uid, kpExamScoringDbInserIndexCacheDto);
    }
}
